﻿/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../global/head.h"
#include "../macro/head.h"
#include "aio_helper.h"
#include "aio_impl.h"
#include "aio_tcp.h"
#include "aio_udp.h"

/////////////////////////////////////////////////////////////////////////////////////////
// 
namespace xos_aio
{
    aio_helper::aio_helper( aio_impl * pAioImpl ) : m_pAioImpl( pAioImpl )
    {
    }

    aio_helper::~aio_helper()
    {
    }

    ////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // epoll event
    // 
    int aio_helper::epoll_proc( aio_key * lpKey, int nFilter, int nFlags, int nData )
    {
        using namespace std;
        int nRet = 0;

        int nType = lpKey->m_enumHandleType;

        switch( nType )
        {
        case aio_key::H_TYPE_TCP_SERVER:
        case aio_key::H_TYPE_TCP_CONN:
        case aio_key::H_TYPE_TCP_NORM:
            {
                nRet = tcp_proc( lpKey, nFilter, nFlags, nData );
            }
            break;
        case aio_key::H_TYPE_UDP:
            {
                nRet = udp_proc( lpKey, nFilter, nFlags, nData );
            }
            break;
        }

        return nRet;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int aio_helper::tcp_proc( aio_key * lpKey, int nFilter, int nFlags, int nData )
    {
        using namespace std;
        int nRet = 0;

        int eType = lpKey->m_enumHandleType;
        aio_tcp tool( m_pAioImpl );

        switch( eType )
        {
        case aio_key::H_TYPE_TCP_CONN:
            {
                lpKey->m_nCanWriteSize = nData;
                lpKey->m_bCanWrite = true;
                nRet = tool.tcp_connect( lpKey, nFilter );
            }
            break;
        case aio_key::H_TYPE_TCP_SERVER:
            {
                nRet = tool.tcp_accept( lpKey, nFilter );
            }
            break;
        case aio_key::H_TYPE_TCP_NORM:
            {
                if( nFilter & EVFILT_WRITE )
                {
                    lpKey->m_nCanWriteSize = nData;
                    lpKey->m_bCanWrite = true;
                    nRet = tool.tcp_send( lpKey );
                }
                if( nFilter & EVFILT_READ )
                {
                    lpKey->m_nCanReadSize = nData;
                    nRet = tool.tcp_recv( lpKey );
                }
            }
            break;
        }

        return nRet;
    }

    int aio_helper::udp_proc( aio_key * lpKey, int nFilter, int nFlags, int nData )
    {
        using namespace std;
        int nRet = 0;

        aio_udp tool( m_pAioImpl );

        if( nFilter & EVFILT_WRITE )
        {
            lpKey->m_nCanWriteSize = nData;
            lpKey->m_bCanWrite = true;
            nRet = tool.udp_send( lpKey );
        }
        if( nFilter & EVFILT_READ )
        {
            lpKey->m_nCanReadSize = nData;
            nRet = tool.udp_recv( lpKey );
        }

        return nRet;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // process user request 
    // 
    int aio_helper::user_request()
    {
        using namespace std;
        int nRet = 0;

        aio_data::LIST & data_list = m_pAioImpl->m_request_list;

        while( 1  )
        {
            xos_box::i_msg * pMsg = 0;
            aio_data * p = 0;

            data_list.lock();
			if( data_list.size() > 0 )
			{
				p = data_list.front();
				data_list.pop_front();
			}
            data_list.un_lock();

            if( !p )
            {
                break;
            }

            pMsg = p->m_pMsg;

            p->m_pMsg = 0;
            p->release();
            p = 0;

            helper_proc( pMsg );
            pMsg = 0;
        }

        return nRet;
    }

    // 
    // will eat lpMsg
    // 
    int aio_helper::helper_proc( xos_box::i_msg * lpMsg )
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = user_tcp( lpMsg );
        }

        if( 0 == ret )
        {
            ret = user_udp( lpMsg );
        }

        return ret;
    }

    // 
    // will eat lpMsg
    // 
    int aio_helper::user_tcp( xos_box::i_msg * lpMsg )
    {
        int ret = 1;

        int eType = lpMsg->get_int( 0, 0 );
        aio_tcp tcp( m_pAioImpl );

        switch( eType )
        {
        case i_aio::AIO_TCP_INIT:
            {
                tcp.user_init( lpMsg );
            }
            break;
        case i_aio::AIO_TCP_CONNECT:
            {
                tcp.user_connect( lpMsg );
            }
            break;
        case i_aio::AIO_TCP_ACCPET:
            {
                tcp.user_accept( lpMsg );
            }
            break;
        case i_aio::AIO_TCP_RECV:
            {
                tcp.user_recv( lpMsg );
            }
            break;
        case i_aio::AIO_TCP_SEND:
            {
                tcp.user_send( lpMsg );
            }
            break;
        case i_aio::AIO_TCP_SHUTDOWN:
            {
                tcp.shut_down( lpMsg );
            }
            break;
        case i_aio::AIO_TCP_CLOSE:
            {
                tcp.close_net( lpMsg );
            }
            break;
        default:
            {
                ret = 0;
            }
            break;
        }

        return ret;
    }

    // 
    // will eat lpMsg
    // 
    int aio_helper::user_udp( xos_box::i_msg * lpMsg )
    {
        int ret = 1;

        int eType = lpMsg->get_int( 0, 0 );
        aio_udp udp( m_pAioImpl );

        switch( eType )
        {
        case i_aio::AIO_UDP_INIT:
            {
                udp.user_init( lpMsg );
            }
            break;
        case i_aio::AIO_UDP_RECV:
            {
                udp.user_recv( lpMsg );
            }
            break;
        case i_aio::AIO_UDP_SEND:
            {
                udp.user_send( lpMsg );
            }
            break;
        case i_aio::AIO_UDP_SHUTDOWN:
            {
                udp.shut_down( lpMsg );
            }
            break;
        case i_aio::AIO_UDP_CLOSE:
            {
                udp.close_net( lpMsg );
            }
            break;
        default:
            {
                ret = 0;
            }
            break;
        }

        return ret;
    }

} // xos_aio
